/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "transaction/rs_render_service_client.h"

#include <event_handler.h>
#include <string>
#include "platform/common/rs_log.h"
#include "rs_surface_ohos.h"
#include "rs_vsync_client_ohos.h"

namespace Keels {
namespace Rosen {

std::shared_ptr<RSRenderServiceClient> RSRenderServiceClient::CreateRenderServiceClient()
{
    static std::shared_ptr<RSRenderServiceClient> client = std::make_shared<RSRenderServiceClient>();
    return client;
}

std::shared_ptr<RSSurface> RSRenderServiceClient::CreateNodeAndSurface(const RSSurfaceRenderNodeConfig& config)
{
    return std::make_shared<RSSurfaceOhos>(static_cast<ANativeWindow*>(config.additionalData));
}

class VSyncReceiverOhos : public VSyncReceiver {
public:
    VSyncReceiverOhos(const std::shared_ptr<Keels::AppExecFwk::EventHandler> handler) : handler_(handler) {}
    ~VSyncReceiverOhos() = default;
    VsyncError Init() override
    {
        client_ = RSVsyncClient::Create();
        if (client_ == nullptr) {
            return GSERROR_NO_MEM;
        }

        return GSERROR_OK;
    }

    VsyncError RequestNextVSync(FrameCallback callback) override
    {
        if (client_ == nullptr) {
            return GSERROR_NOT_INIT;
        }

        auto func = [callback, this](int64_t time, int64_t frameCount) {
            handler_->PostTask([callback, time, frameCount]() {
                if (callback.callbackWithId_) {
                    callback.callbackWithId_(time, frameCount, callback.userData_);
                } else {
                    callback.callback_(time, callback.userData_);
                }
            });
        };
        client_->SetVsyncCallback(func);
        client_->RequestNextVsync();
        return GSERROR_OK;
    }

    VsyncError SetVSyncRate(FrameCallback callback, int32_t rate) override
    {
        if (client_ == nullptr) {
            return GSERROR_NOT_INIT;
        }

        return GSERROR_OK;
    }

private:
    std::unique_ptr<RSVsyncClient> client_ = nullptr;
    std::shared_ptr<Keels::AppExecFwk::EventHandler> handler_ = nullptr;
};

std::shared_ptr<VSyncReceiver> RSRenderServiceClient::CreateVSyncReceiver(const std::string& name,
    const std::shared_ptr<Keels::AppExecFwk::EventHandler>& looper, uint64_t id, NodeId windowNodeId)
{
    return std::make_shared<VSyncReceiverOhos>(looper);
}
} // namespace Rosen
} // namespace Keels
